/**
 * @brief 2.5.3 decltype类型说明符
 * 希望从表达式的类型推断出要定义的变量的类型，但是不想用该表达式的值初始化变量。
 * 为了满足这一要求，C++11新标准引入了第二种类型说明符decltype，它的作用是选择并返回操作数的数据类型。
 * @param argc 
 * @param argv 
 * @return int 
 */

int f(); // 声明f函数，没有进行定义

int main(int argc, char const *argv[])
{
    // 类型说明符decltype，它的作用是选择并返回操作数的数据类型
    decltype(f()) sum; // sum的类型就是函数f的返回类型，编译器并不实际调用f（也就是说只用到f的声明）

    // 如果decltype使用的表达式是一个变量，则decltype返回该变量的类型（包括顶层const和引用在内）
    const int ci = 0, &cj = ci;
    decltype(ci) x = 0; // x的类型是const int
    decltype(cj) y = x; // y的类型是const int&，y绑定到变量x上
    // decltype(cj) z; // 错误，z是一个引用，必须初始化

    // 如果表达式的内容是解引用操作，则decltype将得到引用类型。
    int i = 42, *p = &i, &r = i;
    decltype(r + 0) b; // 正确，加法的结果是int，因此b是个未初始化的int
    // decltype(*p) c; // 错误，c是int&，必须初始化

    // 如果给变量加上了一层或多层括号，编译器就会把它当成是一个表达式。
    // 变量是一种可以作为赋值语句左值的特殊表达式，所以这样的decltype就会得到引用类型
    // decltype((i)) d; // 错误，d是int&，必须初始化
    decltype(i) e; // 正确，e是未初始化的int

    return 0;
}
